package main

import (
	"fmt"
	"log"
	"reflect"
)

type EmptyInterface interface {
}

type WithFuncInterface interface {
	Func()
}
type TestStruct struct {
	Member int
}

func (t *TestStruct) Func() {
	log.Printf("hahah \n")
}

func TestEmptyInterface(i EmptyInterface) {
	fmt.Printf("in TestEmptyInterface(): %+v\n", &i)                  // 0xc000086030
	fmt.Printf("Interface in TestEmptyInterface: %v\n", i == nil)     // false ====>  对比 main() 方法当中的方法
	fmt.Printf("Interface Reflect: %v\n", reflect.ValueOf(i) == i)    // false
	fmt.Printf("Interface Reflect: %v\n", reflect.ValueOf(i))         // <nil>
	fmt.Printf("Interface Reflect: %v\n", reflect.ValueOf(nil))       // <invalid reflect.Value>
	fmt.Printf("Interface Reflect: %v\n", reflect.ValueOf(i).IsNil()) // true, 如果 i 是 通过 ValueOf() 创建的,那么 i == nil ,如果 v 为零值,那么将会 panic
}

func TestWithFuncInterface(i WithFuncInterface) {
	fmt.Printf("Func Interface: %v\n", i == nil)
}

func TestWithFuncStruct(i *TestStruct) {
	fmt.Printf("Struce Interface: %v\n", i == nil)
}

// 非常好的视频地址
// nil 的理解: https://speakerdeck.com/campoy/understanding-nil?slide=49
func main() {
	var test *TestStruct = nil
	fmt.Printf("in main(): %+v\n", &test)                // 0xc000080018
	fmt.Printf("Interface in main(): %v\n", test == nil) // true  ====>  对比 TestEmptyInterface() 方法当中的方法

	TestEmptyInterface(test)
	TestWithFuncInterface(test)
	TestWithFuncStruct(test)
	test.Func() // hahah ,虽然 test 为 nil ,但是不会报错 !!!
	//fmt.Printf("%v", test.Member) // panic
}
